package engine.utils
{
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.DisplayObject;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	public class CollisionUtils
	{
		/**
		 * Calculates a pixel-perfect collision Rectangle.
		 * 
		 * @see http://gskinner.com/blog/archives/2005/10/source_code_sha.html
		 */
		public static function collisionRect(display1:DisplayObject, display2:DisplayObject, precise:Boolean = false, tolerance:int = 255):Rectangle
		{
			var rect1:Rectangle = display1.getBounds(display1.stage);
			var rect2:Rectangle = display2.getBounds(display2.stage);
			
			var intersection:Rectangle = rect1.intersection(rect2);
			
			if(!precise) return intersection;
			
			intersection.x 		= Math.floor(intersection.x);
			intersection.y 		= Math.floor(intersection.y);
			intersection.width 	= Math.ceil(intersection.width);
			intersection.height = Math.ceil(intersection.height);
			
			if(intersection.isEmpty()) return intersection;
			
			var data:BitmapData = new BitmapData(intersection.width, intersection.height, false);
			
			var matrix:Matrix = display1.transform.concatenatedMatrix;
			matrix.translate(-intersection.left, -intersection.top);
			
			data.draw(display1, matrix, new ColorTransform(1, 1, 1, 1, 255, -255, -255, tolerance), BlendMode.NORMAL);
			
			matrix = display2.transform.concatenatedMatrix;
			matrix.translate(-intersection.left, -intersection.top);
			
			data.draw(display2, matrix, new ColorTransform(1, 1, 1, 1, 255, 255, 255, tolerance), BlendMode.DIFFERENCE);
			
			var overlap:Rectangle = data.getColorBoundsRect(0xFFFFFFFF,0xFF00FFFF);
			overlap.offset(intersection.left, intersection.top);
			
			data.dispose();
			data = null;
			
			return overlap;
		}
		
		public static function isColliding(display1:DisplayObject, display2:DisplayObject, precise:Boolean = false, tolerance:int = 255):Boolean
		{
			return !CollisionUtils.collisionRect(display1, display2, precise, tolerance).isEmpty();
		}
		
		public static function isPointColliding(x:Number, y:Number, container:DisplayObject, display:DisplayObject, shapeFlag:Boolean = true):Boolean
		{
			var point:Point = DisplayUtils.localToLocal(x, y, container, container.stage);
			return display.hitTestPoint(point.x, point.y, shapeFlag);
		}
	}
}